package user

import (
	"cross-shard-channel/common"
	"encoding/json"
	"github.com/eywa-protocol/bls-crypto/bls"
	"io/ioutil"
	"net/http"
)

// 定义回复请求的函数
func InitCloseRespond(w http.ResponseWriter, r *http.Request) {
	//println("Begin InitCloseRespond")

	// 定义基本结构
	var requestObject InitClose
	var responseObject InitCloseResponse
	var err error

	// 分析请求数据
	body, _ := ioutil.ReadAll(r.Body)
	err = json.Unmarshal(body, &requestObject)
	if err != nil {
		println(err.Error())
		return
	}

	// get local information about channel
	tarChannel := UN.GetChannelFromNode(requestObject.Cid)
	if tarChannel == nil {
		return
	}

	responseObject.Cid = requestObject.Cid
	responseObject.Ack = true

	// 发送response
	ret, err := json.Marshal(responseObject)
	if err != nil {
		println("response marshal error\n", err.Error())
		return
	}
	n, err := w.Write(ret)
	if err != nil {
		println(err.Error())
		return
	} else if n != len(ret) {
		println("send to less")
		return
	}

	//println("InitCloseRespond success")
	return
}

func CloseCreateRespond(w http.ResponseWriter, r *http.Request) {
	//println("Begin CloseCreateRespond")

	// 定义基本结构
	var requestObject CloseCreate
	var responseObject CloseCreateResponse
	var err error

	// 分析请求数据
	body, _ := ioutil.ReadAll(r.Body)
	err = json.Unmarshal(body, &requestObject)
	if err != nil {
		println(err.Error())
		return
	}

	// get local information about channel
	UN.Lock()
	myMainPub := UN.Pub
	myMainPri := UN.Pri
	UN.Unlock()

	ch := UN.GetChannelFromNode(requestObject.Cid)
	ch.Lock()
	myChPri := ch.MyChPri
	myNotifyPri := ch.MyNotifyPri
	myChBalance := ch.MyBalance
	chType := ch.Type
	ch.Unlock()

	// 构造commit交易
	myMainSig := requestObject.TxClose.Sign(myMainPri)
	myChSig := requestObject.TxClose.Sign(myChPri)
	myNotifySig := requestObject.TxClose.Sign(myNotifyPri)

	var sig0 bls.Signature
	var sig1 bls.Signature
	var sig2 bls.Signature

	if chType == 1 {
		sig0 = requestObject.ChSigA.Aggregate(myChSig)       // for channel fund
		sig1 = requestObject.MainSigA.Aggregate(myNotifySig) // for NotifyUTXOA
		sig2 = myMainSig.Aggregate(requestObject.NotifySigA) // for NotifyUTXOB
	} else {
		sig0 = myChSig.Aggregate(requestObject.ChSigA)       // for channel fund
		sig1 = myNotifySig.Aggregate(requestObject.MainSigA) // for NotifyUTXOA
		sig2 = requestObject.NotifySigA.Aggregate(myMainSig) // for NotifyUTXOB
	}
	requestObject.TxClose.Sigs = []bls.Signature{sig0, sig1, sig2}
	if !requestObject.TxClose.Verify() {
		println("Close Create Error: the close tx construct fail!")
		return
	}

	// 构建response object
	responseObject.Cid = requestObject.Cid
	responseObject.MainSigB = myMainSig
	responseObject.ChSigB = myChSig
	responseObject.NotifySigB = myNotifySig

	// 发送response
	ret, err := json.Marshal(responseObject)
	if err != nil {
		println("response marshal error\n", err.Error())
		return
	}
	n, err := w.Write(ret)
	if err != nil {
		println(err.Error())
		return
	} else if n != len(ret) {
		println("send to less")
		return
	}

	// 构建退款交易
	refundInputs := []common.UTXO{requestObject.TxClose.Output[1]}
	refundOutputs := []common.UTXO{common.UTXO{
		PublicKey: myMainPub,
		Tx_id:     nil,
		Balance:   myChBalance,
	}}
	refundTx := common.GenerateTransactionByUTXO(refundInputs, refundOutputs, 0)
	refundTx.Sigs = []bls.Signature{refundTx.Sign(myChPri)}
	if !refundTx.Verify() {
		println("Close ERROR: the last refund tx construct fail!")
	}

	// 修改通道状态
	ch.Lock()
	ch.TxClose = requestObject.TxClose
	ch.TxRefunds = append(ch.TxRefunds, *refundTx)
	ch.Unlock()

	//println("CloseCreateRespond Success")
	return
}
